<?php
/*
  +------------------------------------------------------------------------+
  | PLU																	   |
  +------------------------------------------------------------------------+
  | Copyright (c) 2013-2015 PLU Team (http://www.plu.cn)				   |
  +------------------------------------------------------------------------+
  | This source file is subject to the New BSD License that is bundled     |
  | with this package in the file docs/LICENSE.txt.                        |
  |                                                                        |
  | If you did not receive a copy of the license and are unable to         |
  | obtain it through the world-wide-web, please send an email             |
  | to license@plu.cn so we can send you a copy immediately.               |
  +------------------------------------------------------------------------+
  | Authors: wolftankk <wolftankk@plu.cn>                                  |
  +------------------------------------------------------------------------+
*/
namespace Plu\qdh;

use Phalcon\Loader,
    Phalcon\Config,
	Phalcon\Mvc\Application as ApplicationBase,
	Phalcon\DI\FactoryDefault,
	Phalcon\Mvc\View,
	Phalcon\Mvc\View\Engine\Volt,
    Phalcon\Logger\Adapter\File as LoggerEngine,
    Plu\Library\Logger\Metric as MetricEngine,

	Phalcon\Events\Manager as EventsManager,
	Phalcon\Db\Adapter\Pdo\Mysql as MysqlDB, // mysql
	Phalcon\Mvc\Dispatcher,
	Phalcon\Cache\Backend\File as FileCache,
	Phalcon\Cache\Frontend\Igbinary as FrontCache,
	Phalcon\Mvc\Model\Metadata\Files as FileMetaData,
	Phalcon\Session\Adapter\Files as SessionAdapter,
	Phalcon\Flash\Session as FlashSession,

	Plu\qdh\Plugins\HttpResponsePlugin,
	Plu\Library\Plugins\PermissionCheckerPlugin,
	Plu\Library\Services\Utility\UrlService,
	Plu\qdh\Services\PassportService as Passport,
    Plu\Library\Services\Report\LogRecord\LogRecordService,
    Plu\Library\Services\Redis\RedisService,

    Plu\Library\Error\ErrorHandler;

define("APP_PATH", __DIR__.DIRECTORY_SEPARATOR);
define("APP_CACHE_PATH", APP_PATH."cache".DIRECTORY_SEPARATOR);
define("PLU_PATH", dirname(dirname(APP_PATH)).DIRECTORY_SEPARATOR);

class Application extends ApplicationBase {
	private static $mode = "dev";

	const MODE_PRODUCTION = "product";
	const MODE_TEST		  = "test";
	const MODE_DEVELOPMENT= "dev";

	/**
	 * 网站模式
	 */
	const APPTYPE_WEB	 = "web";
	/**
	 * 命令行模式
	 */
	const APPTYPE_CI	 = "ci";

    const MEMCACHE_LIFETIME = 120;

	private $APP_TYPE = self::APPTYPE_WEB;

	protected $loader;
	protected $di;

	private $appConfigDirectory;
    private $globalConfigDirectory;

	private $eventManager;

	protected function _registerNamespace() {
        $library_path = PLU_PATH."Library".DIRECTORY_SEPARATOR;

		$this->loader->registerNamespaces(array(
			"Plu\Library" => $library_path."Plu",
            'Plu\qdh'    => APP_PATH,
		));
	}

	public function setApplicationType($type) {
		if ($type == self::APPTYPE_WEB || $type == self::APPTYPE_CI) {
			$this->APP_TYPE = $type;
		}
	}

	private function getLogger($name) {
		$logfile_dir = APP_PATH.'/logs/debug.log';
		$logger = new LoggerEngine($logfile_dir);
		return $logger;
	}

	public static function getCurrentMode() {
		return self::$mode;
	}

	protected function _registerServices() {
        //新版的config 需要全局下的app和本项目的config做一次合并
        $config = call_user_func(function(){
            $globalAppConfig = require($this->appConfigDirectory."app.php");
            $globalAppConfig = new Config($globalAppConfig);

            require($this->appConfigDirectory."config.php");

			$appConfig = $globalAppConfig->merge($config);	

            return $appConfig;
		});
		

        //申明环境，在新版本中di的func this作用域被改变了
        $app = $this;

		if (isset($config['mode'])) {
			self::$mode = $config->mode;
		}
		
		$this->di['config'] = $config;

		$this->di['dispatcher'] = function() use ($app) {
			$dispatcher = new Dispatcher();

			$app->eventManager->attach('dispatch', new HttpResponsePlugin());

			$app->eventManager->attach('dispatch', new PermissionCheckerPlugin());

            $dispatcher->setEventsManager($app->eventManager);
			//注册默认controller目录
			$dispatcher->setDefaultNamespace('Plu\qdh\Controllers');

			return $dispatcher;
		};

		$this->di->set('voltService', function($view, $di) {
			$volt = new Volt($view, $di);

			$volt->setOptions(array(
				'compiledPath' => APP_CACHE_PATH."caches_template".DIRECTORY_SEPARATOR,
				'compiledExtension' => '.compiled',
				'compileAlways' => false
			));

			$compiler = $volt->getCompiler();
			$compiler->addFilter('array_slice', 'array_slice');
			$compiler->addFunction('create_url', function($resolvedArgs, $exprArgs) {
				return 'Plu\Library\Services\Utility\UrlService::createUrl('.$resolvedArgs.')';
			});
            $compiler->addFunction('explode_str', function($str) {
                return explode(",", $str);
            });
			
			return $volt;
		});


		$this->di->set('view', function() {
			$view = new View();
			$view->setViewsDir(APP_PATH."views");

			$view->registerEngines(array(
				".html" => 'voltService'
			));

			return $view;
		}, true);

		$this->di['router'] = function() use($app) {
			$router = include $app->appConfigDirectory."router.php";

			return $router;
		};

		$this->di['logger'] = function() use($app) {
			$logger = $app->getLogger("debug");
			return $logger;
		};

		/**
		 * 数据库设定, 自动读取配置中的所有数据库
		 */
		call_user_func(function() {
			$logger = $this->getLogger('mysql');
			$configs = include $this->appConfigDirectory."mysql.php";

            $app = $this;
			foreach ($configs as $name => $_config) {
				$this->di['db.'."$name"] = function() use ($logger, $name, $_config, $app) {
					$app->eventManager->attach('db', function($event, $connection) use ($logger,$name) {
						if ($event->getType() == 'afterQuery') {
							//$logger->log("[$name]: " .$connection->getRealSQLStatement(), \Phalcon\Logger::INFO);
						}
					});
					$mysql = new MysqlDB($_config);
					$mysql->setEventsManager($app->eventManager);

					return $mysql;
				};
			}
		});


		/**
		 * redis 设定
		 */
		call_user_func(function() {
			$configs = include $this->appConfigDirectory."redis.php";
            $app = $this;
			foreach ($configs as $name => $_config) {
                $this->di->attempt('redis.'.$name, function() use ($name) {
                    return new RedisService($name);
                });
			}
		});

		$this->di->set('flash', function(){
			return new FlashSession(array(
				'success'=>'alert alert-success',
				'error'=>'alert alert-danger',
				'notice'=>'alert alert-warning',
			));
		});

		$this->cookies->useEncryption(false);

		/**
		 * session
		 */
		//$this->di['session'] = function() {
		//	$domain = UrlService::domain();

		//	@ini_set("session.cookie_domain", ".".$domain);
		//	@ini_set("session.name", 'PLULOGINSESSID');
		//	@ini_set("session.cache_expire", 10);

		//	//正式环境下 放在内存中
		//	if (self::$mode == self::MODE_PRODUCTION) {
		//		@ini_set("session.save_path", "2;/dev/shm/sessions");
		//	} else {
		//		@ini_set("session.save_path", APP_CACHE_PATH."sessions");
		//	}

		//	$session = new SessionAdapter();
		//	$session->start();
		//	return $session;
		//};

		/**
		 * 缓存设定
		 */
		$this->di['cache'] = function() use ($app) {
			//1 days
			$frontCache = new FrontCache(array(
                'lifetime' => self::MEMCACHE_LIFETIME, 
			));

            if (self::$mode == self::MODE_PRODUCTION) {
                $configs = include $app->globalConfigDirectory."memcached.php";
                $configs = $configs["webcache"];
                $configs['prefix'] = "qdh.";
                $configs['statsKey'] = "";
                return new \Phalcon\Cache\Backend\Libmemcached($frontCache, $configs);
            } else {
                return new FileCache($frontCache, array(
                    'cacheDir' => APP_CACHE_PATH."caches_data".DIRECTORY_SEPARATOR
                ));

            }
		};

		/**
		 * Model Cache
		 */
		$this->di['modelsCache'] = function() use($app) {
			return $app->di->get('cache');
		};

		$this->di['modelsMetadata'] = function() {
			//1 days
			$metaDataCache = new FileMetaData(array(
				'lifetime' => 86400,
				'metaDataDir' => APP_CACHE_PATH."caches_metadata".DIRECTORY_SEPARATOR
			));

			return $metaDataCache;
		};


        //日志
        $this->di['recordLog'] = function() use ($app) {
            $logConfig = include $app->appConfigDirectory. "log.php";
            $typeConfig = $logConfig[self::$mode];
            $theLog = new LogRecordService("stark", $typeConfig);
            return $theLog;
        };

		$this->di['passport'] = function() use($app) {
			$passport = new Passport();
			return $passport;
		};
	}

	public function main() {
		date_default_timezone_set('Asia/Shanghai');
		$this->eventManager = new EventsManager();

		//声明一些私有变量
        $this->globalConfigDirectory = PLU_PATH."config".DIRECTORY_SEPARATOR;
		$this->appConfigDirectory = APP_PATH."config".DIRECTORY_SEPARATOR;

		$this->loader = new Loader();

		//将三方库加入到loader中
		//注册controller 和 model
		$this->_registerNamespace();
		$this->loader->register();

		//注册业务
		$this->di = new FactoryDefault();
		$this->_registerServices();
		//register di
		$this->setDI($this->di);

        // $errorHandler = new ErrorHandler($this->logger, [
        //     'errorLevel' => E_ALL & ~E_NOTICE
        // ]);
        // $errorHandler->register();

		if ($this->APP_TYPE == self::APPTYPE_WEB) {
			echo $this->handle()->getContent();
		}
	}
}

?>
